import React, { Component } from 'react';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import s from './FontPicker.less';

export default class FontPicker extends Component {
    state = {
        isDragging: false,
    };

    componentDidMount() {
        this.pointer.addEventListener('touchstart', this.dragStart);
        this.pointer.addEventListener('touchmove', this.dragMove);
        this.pointer.addEventListener('touchend', this.dragEnd);
    }

    componentWillUnmount() {
        this.pointer.removeEventListener('touchstart', this.dragStart);
        this.pointer.removeEventListener('touchmove', this.dragMove);
        this.pointer.removeEventListener('touchend', this.dragEnd);
    }

    dragStart = e => {
        const { width, left } = this.line.getBoundingClientRect();
        this.setState({
            containerLeft: left,
            containerWidth: width,
            isDragging: true,
            currentX: e.touches[0].pageX,
        });
    };

    dragMove = e => {
        // @TODO 这里需要对触发频率做下限制
        e.preventDefault();
        let { pageX } = e.touches[0];
        const { containerLeft, containerWidth } = this.state;
        // 限制滑块滑动范围
        if (pageX < containerLeft) {
            pageX = containerLeft;
        }
        if (pageX > containerWidth + containerLeft) {
            pageX = containerWidth + containerLeft;
        }
        const fontMap = Object.keys(this.props.styleMap)
            .map((_, index, fonts) => [
                _,
                Math.abs(pageX - containerLeft - (containerWidth / (fonts.length - 1)) * index),
            ])
            .sort((a, b) => a[1] - b[1]);

        this.setState(
            {
                isDragging: true,
                currentX: pageX,
            },
            () => {
                if (!this.props.editorState.getCurrentInlineStyle().has(fontMap[0][0])) {
                    this.props.onChange(fontMap[0][0]);
                }
            }
        );
    };

    dragEnd = () => {
        this.setState(
            {
                isDragging: false,
                currentX: 0,
                applyTransition: true,
            },
            () => {
                setTimeout(() => {
                    this.setState({ applyTransition: false });
                    this.props.onClose();
                }, 500);
            }
        );
    };

    setFont = type => () => {
        this.props.onChange(type, true);
    };

    render() {
        const fonts = Object.keys(this.props.styleMap);
        const currentStyle = this.props.editorState.getCurrentInlineStyle();
        let activeIndex = fonts.findIndex(type => currentStyle.has(type));
        // 若没有对应字体，则将默认字体选中, 16px
        activeIndex = activeIndex !== -1 ? activeIndex : 2;
        return (
            <div className={s.root}>
                <div
                    className={s.line}
                    ref={node => {
                        this.line = node;
                    }}
                >
                    {fonts.map((type, i) => (
                        <div
                            key={type}
                            className={s.tick}
                            style={{ left: `${(100 * i) / (fonts.length - 1)}%` }}
                            onClick={this.setFont(type)}
                        />
                    ))}
                    <div
                        ref={node => {
                            this.pointer = node;
                        }}
                        className={classnames(s.pointer, { [s.transition]: this.state.applyTransition })}
                        style={{
                            left: this.state.isDragging
                                ? this.state.currentX - this.state.containerLeft
                                : `${(100 * activeIndex) / (fonts.length - 1)}%`,
                        }}
                        onClick={this.props.onClose}
                    />
                </div>
            </div>
        );
    }
}

FontPicker.propTypes = {
    editorState: PropTypes.shape({
        getCurrentInlineStyle: PropTypes.func.isRequired
    }).isRequired,
    styleMap: PropTypes.shape({}).isRequired,
    onChange: PropTypes.func.isRequired,
    onClose: PropTypes.func.isRequired,
};
